<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Spring Boot动态装配指南</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            background-color: #f8fafc;
            color: #1e293b;
        }
        .hero {
            background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%);
        }
        .code-block {
            background-color: #1e293b;
            border-left: 4px solid #2563eb;
        }
        .card {
            transition: all 0.3s ease;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
        }
        .card:hover {
            transform: translateY(-2px);
            box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
        }
        .highlight {
            position: relative;
            padding: 1px 4px;
            border-radius: 3px;
            background-color: rgba(37, 99, 235, 0.1);
            color: #2563eb;
            font-weight: 500;
        }
        .footer {
            background-color: #1e293b;
        }
        .mermaid-container {
            background-color: white;
            border-radius: 0.5rem;
            padding: 1.5rem;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
        }
    </style>
</head>
<body>
    <header class="hero text-white py-20">
        <div class="container mx-auto px-6 max-w-5xl">
            <div class="flex flex-col items-center text-center">
                <h1 class="text-4xl md:text-5xl font-bold mb-4 font-serif">Spring Boot 动态装配机制</h1>
                <p class="text-xl md:text-2xl mb-8 max-w-3xl">深入理解 DeferredImportSelector 接口的强大灵活性</p>
                <div class="flex space-x-4">
                    <a href="#intro" class="px-6 py-3 bg-white text-blue-600 font-medium rounded-lg hover:bg-gray-100 transition duration-300">
                        <i class="fas fa-book-open mr-2"></i>开始阅读
                    </a>
                    <a href="#example" class="px-6 py-3 border-2 border-white text-white font-medium rounded-lg hover:bg-white hover:text-blue-600 transition duration-300">
                        <i class="fas fa-code mr-2"></i>查看示例
                    </a>
                </div>
            </div>
        </div>
    </header>

    <main class="container mx-auto px-6 py-12 max-w-5xl">
        <section id="intro" class="mb-16">
            <h2 class="text-3xl font-bold mb-6 font-serif border-b-2 border-gray-200 pb-4">动态装配的核心机制</h2>
            <div class="prose max-w-none">
                <p class="text-lg mb-6">在Spring Boot中，可以利用 <span class="highlight">DeferredImportSelector</span> 接口来实现自动装配。<span class="highlight">DeferredImportSelector</span> 接口允许在运行时根据条件选择性地导入配置类。</p>
                
                <p class="text-lg mb-6">与普通的 <span class="highlight">ImportSelector</span> 不同，<span class="highlight">DeferredImportSelector</span> 会在所有其他配置类处理完成后才执行，这使得它特别适合处理需要评估其他配置状态的动态导入场景。</p>
            </div>
        </section>

        <section id="principle" class="mb-16">
            <h2 class="text-3xl font-bold mb-6 font-serif border-b-2 border-gray-200 pb-4">工作原理</h2>
            <div class="grid md:grid-cols-2 gap-8">
                <div class="mermaid-container">
                    <div class="mermaid">
                        sequenceDiagram
                            participant App as 应用启动
                            participant Container as Spring容器
                            participant Selector as DeferredImportSelector
                            
                            App->>Container: 启动Spring应用
                            Container->>Selector: 延迟执行selectImports()
                            Selector->>Selector: 评估当前环境条件
                            Selector-->>Container: 返回配置类列表
                            Container->>Container: 注册选择的配置类
                            Container-->>App: 完成应用上下文初始化
                    </div>
                </div>
                <div class="prose">
                    <h3 class="text-2xl font-semibold mb-4">执行流程详解</h3>
                    <ol class="list-decimal pl-6 space-y-3">
                        <li>Spring应用启动并开始初始化容器</li>
                        <li>容器识别到 <span class="highlight">@Import</span> 注解引用了 <span class="highlight">DeferredImportSelector</span></li>
                        <li>先处理其他常规配置类，等待主要配置处理完成</li>
                        <li>在所有其他配置处理完毕后，调用 <span class="highlight">selectImports</span> 方法</li>
                        <li>根据运行时条件返回需要导入的配置类全限定名</li>
                        <li>容器注册这些配置类并继续完成初始化</li>
                    </ol>
                    <div class="mt-6 p-4 bg-blue-50 rounded-lg border border-blue-100">
                        <i class="fas fa-info-circle text-blue-500 mr-2"></i>
                        <span class="text-blue-800">这种延迟执行机制确保了选择器可以基于完整的应用程序状态做出决策。</span>
                    </div>
                </div>
            </div>
        </section>

        <section id="example" class="mb-16">
            <h2 class="text-3xl font-bold mb-6 font-serif border-b-2 border-gray-200 pb-4">实现示例</h2>
            <div class="grid md:grid-cols-2 gap-8">
                <div class="card bg-white rounded-xl p-6">
                    <div class="flex items-center mb-4">
                        <div class="w-3 h-3 rounded-full bg-red-500 mr-2"></div>
                        <div class="w-3 h-3 rounded-full bg-yellow-500 mr-2"></div>
                        <div class="w-3 h-3 rounded-full bg-green-500 mr-2"></div>
                        <div class="ml-auto text-sm text-gray-500">Selector.java</div>
                    </div>
                    <div class="code-block rounded-lg p-4 text-gray-100 overflow-x-auto">
                        <pre><code>public class MyAutoConfigurationSelector 
    implements DeferredImportSelector {

    @Override
    public String[] selectImports(
        AnnotationMetadata metadata) {
        
        // 在这里根据条件选择配置类
        if (someCondition) {
            return new String[] {
                "com.example.MyConfig1"
            };
        } else {
            return new String[] {
                "com.example.MyConfig2"
            };
        }
    }
}</code></pre>
                    </div>
                    <div class="mt-4 text-sm text-gray-600">
                        <p><i class="fas fa-lightbulb text-yellow-500 mr-2"></i> <span class="highlight">someCondition</span> 可以是环境变量、Bean存在性检查或其他运行时条件</p>
                    </div>
                </div>

                <div class="card bg-white rounded-xl p-6">
                    <div class="flex items-center mb-4">
                        <div class="w-3 h-3 rounded-full bg-red-500 mr-2"></div>
                        <div class="w-3 h-3 rounded-full bg-yellow-500 mr-2"></div>
                        <div class="w-3 h-3 rounded-full bg-green-500 mr-2"></div>
                        <div class="ml-auto text-sm text-gray-500">Configuration.java</div>
                    </div>
                    <div class="code-block rounded-lg p-4 text-gray-100 overflow-x-auto">
                        <pre><code>@Configuration
@Import(MyAutoConfigurationSelector.class)
public class MyAutoConfiguration {
    // 可能的其他配置
}</code></pre>
                    </div>
                    <div class="mt-6">
                        <div class="code-block rounded-lg p-4 text-gray-100 overflow-x-auto">
                            <pre><code>@Import(MyAutoConfiguration.class)
public class MyBootApp {
    public static void main(String[] args) {
        ApplicationContext ctx = new 
            AnnotationConfigApplicationContext(
                MyBootApp.class);
        
        // 获取动态注册的Bean
        ctx.getBeansOfType(MyConfig1.class);
    }
}</code></pre>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <section id="best-practices" class="mb-16">
            <h2 class="text-3xl font-bold mb-6 font-serif border-b-2 border-gray-200 pb-4">最佳实践</h2>
            <div class="grid md:grid-cols-3 gap-6">
                <div class="card bg-white p-6 rounded-lg">
                    <div class="text-blue-500 mb-4">
                        <i class="fas fa-clock fa-2x"></i>
                    </div>
                    <h3 class="text-xl font-semibold mb-3">执行时机</h3>
                    <p class="text-gray-600"><span class="highlight">DeferredImportSelector</span> 在Spring Boot启动过程中的Bean定义加载阶段执行，确保你有足够的信息做决策。</p>
                </div>
                <div class="card bg-white p-6 rounded-lg">
                    <div class="text-blue-500 mb-4">
                        <i class="fas fa-project-diagram fa-2x"></i>
                    </div>
                    <h3 class="text-xl font-semibold mb-3">条件评估</h3>
                    <p class="text-gray-600">充分利用环境变量、配置属性或Bean存在性检查等条件来决定导入哪些配置类。</p>
                </div>
                <div class="card bg-white p-6 rounded-lg">
                    <div class="text-blue-500 mb-4">
                        <i class="fas fa-cubes fa-2x"></i>
                    </div>
                    <h3 class="text-xl font-semibold mb-3">模块化设计</h3>
                    <p class="text-gray-600">将相关配置分组到不同的配置类中，通过选择器按需加载，保持应用模块化。</p>
                </div>
            </div>
        </section>

        <section id="comparison" class="mb-16">
            <h2 class="text-3xl font-bold mb-6 font-serif border-b-2 border-gray-200 pb-4">技术对比</h2>
            <div class="bg-white rounded-xl overflow-hidden shadow-sm">
                <table class="min-w-full divide-y divide-gray-200">
                    <thead class="bg-gray-50">
                        <tr>
                            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">特性</th>
                            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">@Import</th>
                            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">ImportSelector</th>
                            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">DeferredImportSelector</th>
                        </tr>
                    </thead>
                    <tbody class="bg-white divide-y divide-gray-200">
                        <tr>
                            <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">执行时机</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">最早</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">中间</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">最晚</td>
                        </tr>
                        <tr>
                            <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">条件性导入</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">不支持</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">支持</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">支持</td>
                        </tr>
                        <tr>
                            <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">访问应用状态</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">无</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">有限</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">完整</td>
                        </tr>
                        <tr>
                            <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">典型用例</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">静态导入</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">简单条件导入</td>
                            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">复杂条件导入</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </section>

        <section class="bg-blue-50 rounded-xl p-8 mb-16 border border-blue-100">
            <div class="flex flex-col md:flex-row items-center">
                <div class="md:w-2/3 mb-6 md:mb-0">
                    <h3 class="text-2xl font-semibold mb-3">想要了解更多Spring Boot高级特性？</h3>
                    <p class="text-gray-700">探索Spring Boot自动配置的更多可能性，构建更灵活的应用程序架构。</p>
                </div>
                <div class="md:w-1/3 flex justify-center md:justify-end">
                    <a href="http://www.yuque.com/jtostring" class="px-6 py-3 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 transition duration-300">
                        <i class="fas fa-external-link-alt mr-2"></i>访问技术小馆
                    </a>
                </div>
            </div>
        </section>
    </main>

    <footer class="footer text-white py-8">
        <div class="container mx-auto px-6 max-w-5xl">
            <div class="flex flex-col md:flex-row justify-between items-center">
                <div class="mb-4 md:mb-0">
                    <p class="text-gray-300">技术小馆</p>
                </div>
                <div>
                    <a href="http://www.yuque.com/jtostring" class="text-gray-300 hover:text-white transition duration-300">
                        <i class="fas fa-globe mr-2"></i>http://www.yuque.com/jtostring
                    </a>
                </div>
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'linear'
            }
        });
    </script>
</body>
</html>